package com.ls.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ls.config.satoken.SaTokenUtilPy;
import com.ls.controller.user.model.*;
import com.ls.entity.Customer;
import com.ls.entity.SmsTemplate;
import com.ls.entity.SysUser;
import com.ls.enums.RoleEnum;
import com.ls.exception.ErrorEnums;
import com.ls.exception.SysException;
import com.ls.mapper.SysUserMapper;
import com.ls.service.ISysUserService;
import com.ls.utils.Desensitize;
import com.ls.utils.LocalCache;
import com.ls.utils.ResultData;
import com.ls.config.redis.RedisClient;
import com.ls.utils.rsa.RsaUtils;
import com.ls.utils.sms.SendSmsModel;
import com.ls.utils.sms.SmsPyUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;

import static com.ls.constant.SystemConstants.*;
import static com.ls.enums.RoleEnum.ADMIN;
import static com.ls.utils.LocalCache.LOGIN_PREFIX;
import static com.ls.utils.sms.SendSmsModel.VERIFY_CODE_PREFIX;
import static com.ls.utils.sms.SendSmsModel.randomCode;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author TangQuanBin
 * @since 2019-09-13
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements ISysUserService {

    /**
     * #脱敏状态，0 明文 1 脱敏
     */
    @Value("${desensitize.status}")
    private int desensitizeStatus;
    /**
     * RSA公钥
     */
    @Value("${RSA.publicKey}")
    private String publicKey;
    /**
     * RSA私钥
     */
    @Value("${RSA.privateKey}")
    private String privateKey;
//    @Autowired
//    private IProvinceService provinceService;

    @Value("${sms.type}")
    private String smsType;

    private final RedisClient redisClient;

    /**
     * 根据账号查询用户
     *
     * @param phone 账号
     * @return User
     */
    @Override
    public SysUser findUserByPhone(String phone) {
        return getBaseMapper().getUserByPhone(phone);
    }


    @Override
    public ResultData setInitInfo(InitModel model) {
        SysUser sysUser = SaTokenUtilPy.getSysUser();
////        String mobile = currentUser.getPhone();
        String mobile = model.getAdminPhone();
        String verifyCode = model.getVerifyCode();
        // 校验短信验证码
        checkVerifyCode(mobile, verifyCode);
        if (model.getPassword().equals(sysUser.getPassword())) {
            return ResultData.failure("新密码与老密码不能一致！");
        }
        BeanUtil.copyProperties(model, sysUser, CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
        updateUser(sysUser);
        return ResultData.successData(sysUser);
    }

    /**
     * 忘记密码 - 获取短信验证码    getSmsVerifyCode phone 用户手机号  type 验证码类型 0 本号码 1 密保手机
     * 此处企业管理员与其他用户的不同之处在于其他类型用户是没有对应companyId的
     */
    @Override
    public ResultData getSmsVerifyCode(String phone, int type) throws Exception {
        String receivePhone = "";
        String verifyCode = randomCode();
        switch (type) {
            case 0:
                receivePhone = phone;
                break;
            case 1:
                break;
            default:
                return ResultData.failure("type类型错误：" + type);
        }
        if (!receivePhone.matches(TEL_NUMBER_REGEX)) {
            return ResultData.failure(phone + " 不符合手机号码的格式！");
        }

        SendSmsModel sendSmsModel = new SendSmsModel(receivePhone, VERIFY_CODE_PREFIX + verifyCode, phone, verifyCode);
        //校验redis中有没有数据
        String validCode = redisClient.getJsonString(LOGIN_PREFIX + receivePhone);
        if (StringUtils.isNotBlank(validCode)) {
            return ResultData.successMsg("短信验证码已发，10分钟内有效，请不要在10分钟内重复发送");
        }
//        ResultData resultData = SmsPyUtil.sendValidSms(sendSmsModel);
        ResultData sendResultData ;
        sendResultData = SmsPyUtil.sendValidSms(sendSmsModel);

        if(sendResultData == null || !sendResultData.whetherSuccess()){
            return sendResultData;
        }
//        LocalCache.set(LOGIN_PREFIX + model.getMobile() ,model.getValidCode(),DEFAULT_TIMEOUT);
        redisClient.save(LOGIN_PREFIX + receivePhone, verifyCode, (int) LocalCache.DEFAULT_TIMEOUT / 1000);
        return ResultData.successMsg("短信验证码已发，10分钟内有效，请查收");
    }

    @Override
    public ResultData reSetPwd(ReSetPwdModel model) {
        //todo 优先级低 重置密码，暂时不做
        return null;
    }

    @Override
    public ResultData updatePwd(UpdatePwdModel model) {
        SysUser currentUser = SaTokenUtilPy.getSysUser();
        //RSA 算法多次加密后密文不一致，所以比较需要解密
        String pwdDb = RsaUtils.getRsaDecryStr(currentUser.getPassword(), privateKey);
        String oldPwdModel = RsaUtils.getRsaDecryStr(model.getOldPassword(), privateKey);
        String newPwdModel = RsaUtils.getRsaDecryStr(model.getNewPassword(), privateKey);
        if (!pwdDb.equals(oldPwdModel)) {
            return ResultData.failure(ErrorEnums.UNDEFINED_EXCEPTION.getCode(), "旧密码错误");
        }
        if (pwdDb.equals(newPwdModel)) {
            return ResultData.failure(ErrorEnums.UNDEFINED_EXCEPTION.getCode(), "新密码不能与旧密码一致");
        }
        currentUser.setPassword(model.getNewPassword());
        updateUser(currentUser);
        return ResultData.successData(currentUser);
    }

    @Override
    public synchronized String getNextPhoneNumber() {
        Long newPhone = 0L;
        List<Object> list = getBaseMapper().selectObjs(new QueryWrapper<SysUser>().select("phone").orderByDesc("phone").last(" limit 1"));
        if (list != null && list.size() > 0) {
            newPhone = Long.valueOf(list.get(0).toString()) + 1L;
        } else {
            newPhone = Long.valueOf("13000000001");
        }
        return newPhone.toString();
    }

    @Override
    public void checkUserByPhone(String phone) {
        SysUser user = getBaseMapper().getUserByPhone(phone);
        if (user != null) {
            throw new SysException("phone: " + phone + " 在库里已经存在！");
        }
    }

    /**
     * 查询用户列表 超级管理员 客服 省份管理员 代理商
     */
    @Override
    public ResultData getPaging(QueryUserModel model) {
        SysUser currentUser = SaTokenUtilPy.getSysUser();
        Long roleId = currentUser.getRoleId();
        RoleEnum roleEnum = RoleEnum.getRoleEnum(roleId);
        if (roleEnum == null) {
            return ResultData.failure("roleId 为 " + roleId + " 没有对应的角色");
        }
//        LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<SysUser>().ne(SysUser::getRoleId, ADMIN.roleType);
        LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<SysUser>()
                .ge(StringUtils.isNotBlank(model.getBeginSt()), SysUser::getCreateTime, model.getBeginSt())
                .le(StringUtils.isNotBlank(model.getEndSt()), SysUser::getCreateTime, model.getEndSt());
        if (StringUtils.isNoneBlank(model.getPhone())) {
            wrapper.like(SysUser::getPhone, model.getPhone());
        }
        if (StringUtils.isNoneBlank(model.getName())) {
            wrapper.like(SysUser::getUserName, model.getName());
        }
        if (model.getRoleId() != null && model.getRoleId() > 0) {
            wrapper.eq(SysUser::getRoleId, model.getRoleId());
        }
        if (model.getValidFlag() != null) {
            wrapper.eq(SysUser::getValidFlag, model.getValidFlag());
        }
        Page page = new Page(model.getPageNum(), model.getPageSize());
        IPage<SysUser> dtoIPage = getBaseMapper().selectPage(page, wrapper);
        if (desensitizeStatus == DESENTITIZE_HIDDEN) {
            //脱敏
            List<SysUser> userList = dtoIPage.getRecords();
            if (userList != null && userList.size() > 0) {
                for (SysUser user : userList) {
                    user.setPassword("");
                    user.setPhone(Desensitize.getDesensitizeStr(user.getPhone(), Desensitize.DesensitizeType.PHONE.getType()));
                    user.setUserName(Desensitize.getDesensitizeStr(user.getUserName(), Desensitize.DesensitizeType.NAME.getType()));
                }
                dtoIPage.setRecords(userList);
            }
        }
        return ResultData.successData(dtoIPage);
    }


    /**
     * 用户有效状态变更
     */
    @Override
    public ResultData updateStatus(UpdateStatusModel model) {
        SysUser currentUser = SaTokenUtilPy.getSysUser();
        SysUser user = getBaseMapper().selectById(model.getUserId());
        if (user == null) {
            return ResultData.failure("userId :" + model.getUserId() + " 不在库里");
        }
        user.setValidFlag(model.getValidFlag());
        user.setUpdater(currentUser.getUserName());
        user.setUpdateTime(LocalDateTime.now());
        int result = getBaseMapper().updateById(user);
        if (result > 0) {
            return ResultData.success();
        } else {
            return ResultData.failure("数据库更新失败");
        }
    }

    /**
     * 新增用户
     */
    @Override
    public ResultData add(AddUserModel model) {
        log.info("add model:" + model.toString());
        SysUser sysUser = SaTokenUtilPy.getSysUser();

        String phone = model.getPhone();
        SysUser checkUser = this.findUserByPhone(phone);
        if(checkUser !=null){
            String msg = phone + " 手机号码在库里已经存在";
            log.error(msg);
            return ResultData.failure(msg);
        }
        SysUser user = getOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUserName, model.getUserName()));
        if (user != null) {
            String msg = model.getUserName() + " 用户名在库里已经存在";
            log.error(msg);
            return ResultData.failure(msg);
        }
        Long roleId = model.getRoleId();
        RoleEnum roleEnum = RoleEnum.getRoleEnum(roleId);
        if (roleEnum == null) {
            return ResultData.failure("roleId = " + roleId + " 在库里不存在");
        }
        switch (roleEnum) {
            case ADMIN:
                break;
            default:
                break;
        }
        SysUser entity = new SysUser();
        BeanUtils.copyProperties(model, entity);
//        String initPassword = phone.substring(phone.length() - 6);
        String initPassword = model.getPassword();
        entity.setPassword(RsaUtils.encryptedDataOnJava(initPassword, publicKey));

        LocalDateTime now = LocalDateTime.now();
        entity.setCreateTime(now);
        entity.setCreator(sysUser.getUserName());
        entity.setUpdateTime(now);
        int result = getBaseMapper().insert(entity);
        if (result > 0) {
            return ResultData.successData(entity);
        } else {
            return ResultData.failure("数据库插入失败");
        }
    }

    /**
     * 修改用户
     */
    @Override
    public ResultData update(UpdateUserModel model) {
        SysUser sysUser = SaTokenUtilPy.getSysUser();
        Long userId = model.getUserId();
        SysUser entity = getById(userId);
        if (entity == null) {
            return ResultData.failure("用户ID：" + userId + " 不在库里");
        }
        Long roleId = model.getRoleId();
        RoleEnum roleEnum = RoleEnum.getRoleEnum(roleId);
        if (roleEnum == null) {
            return ResultData.failure("roleId = " + roleId + " 在库里不存在");
        }
        String modelName = model.getUserName();
        if (StringUtils.isNotBlank(modelName) && !entity.getUserName().equals(modelName)) {
            int nameCount = count(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUserName, modelName));
            if (nameCount > 0) {
                return ResultData.failure("用户姓名 " + modelName + "在库里已经存在");
            }
        }
        String modelPhone = model.getPhone();
        if (StringUtils.isNotBlank(modelPhone) && !entity.getPhone().equals(modelPhone)) {
            int phoneCount = count(new LambdaQueryWrapper<SysUser>().eq(SysUser::getPhone, modelPhone));
            if (phoneCount > 0) {
                return ResultData.failure("用户手机号码 " + phoneCount + "在库里已经存在");
            }
        }
        switch (roleEnum) {
            default:
                break;
        }
        //null,表示无限制，true表示若父类中属性值为空则忽略，不传给子类 使用 BeanUtil.copyProperties会copy源对象的非空数据，保留目标对象的非空数据 。
        BeanUtil.copyProperties(model, entity, CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
//        BeanUtils.copyProperties(model, entity);
        entity.setUpdater(sysUser.getUserName());
        entity.setUpdateTime(LocalDateTime.now());
        int result = getBaseMapper().updateById(entity);
        if (result > 0) {
            return ResultData.successData(entity);
        } else {
            return ResultData.failure(" 数据库更新失败");
        }
    }

    /**
     * 通过用户id 查询用户信息的接口 数据库同步操作
     */
    @Override
    public ResultData getByUserId(Long userId ){
        if (userId != null && userId.longValue() > 0L) {
            SysUser user = getById(userId);
            if (user == null) {
                return ResultData.failure("用户ID " + userId + " 不存在");
            }
            user.setPassword("");
            if (desensitizeStatus == DESENTITIZE_HIDDEN) {
                user.setPhone(Desensitize.getDesensitizeStr(user.getPhone(), Desensitize.DesensitizeType.PHONE.getType()));
                user.setUserName(Desensitize.getDesensitizeStr(user.getUserName(), Desensitize.DesensitizeType.NAME.getType()));
            }
            return ResultData.successData(user);
        }
        return ResultData.failure("查询条件参数错误");
    }


    public void updateUser(SysUser user) {
        user.setUpdater(user.getUserName());
        user.setUpdateTime(LocalDateTime.now());
        boolean result = updateById(user);
        if (result) {
            user.setPassword(null);
        }
    }

    public void checkVerifyCode(String phone, String verifyCode) {
        // 校验短信验证码
        if (TEST_VERFICATION_CODE.equals(verifyCode)) {
            return;
        }
        String validCodeCache = redisClient.getJsonString(LOGIN_PREFIX + phone);
        if (StringUtils.isBlank(validCodeCache)) {
            throw new SysException("验证码已过期，请查新发送验证码！");
        }
        if (!validCodeCache.equals(verifyCode)) {
            throw new SysException("验证码错误！");
        }
//        Object obj = LocalCache.get(LOGIN_PREFIX + phone);
//        if (obj == null) {
//            throw new SysException(phone + " 验证码已过期，请重新点击发送");
//        }
//        if (!obj.toString().equals(verifyCode)) {
//            throw new SysException(phone + " 验证码错误");
//        }
    }


}

